/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.metashare.grah.pogo

import net.metashare.grah.logic.Predicate
import net.metashare.grah.logic.True
import net.metashare.grah.meta.MetaContext

import net.metashare.grah.Node
import net.metashare.grah.Edge
import net.metashare.grah.GraphObjectDecorator
import net.metashare.grah.Graph
import net.metashare.grah.ResultGraph
import net.metashare.grah.MutableGraph

/**
 *
 * @author dsherema
 */
class SimplePogoGraph implements MutableGraph {

  List nodes = []
  List edges = []
  GraphObjectDecorator decorator = new PogoDecorator()



  def SimplePogoGraph() {
    ExpandoMetaClass.enableGlobally()

  }

  def List nodes(Predicate p = True.instance) {

    return nodes.findAll { p.apply(it) }
  }

  def List<Edge> edges(Predicate p = True.instance) {
    return edges.findAll { p.apply(it) }
  }


  def Graph addNodes(List<Node> nodes) {
    this.nodes.addAll(nodes)

    return new ResultGraph(this, this)
  }

  def Graph addEdges(List<Edge> edges) {
    this.edges.addAll(edges)
    // for each edge, and each NODE in the edge, add them too
    edges.each().each() { add(it)}
    edges.addAll(edges)
    return new ResultGraph(this, this)
  }


  def Graph add(Node n) {

    nodes.add(n)
    n.graph = this
    return new ResultGraph(this, this)

  }

  def Graph add(Edge e) {
    edges.add(e)
    [e.tail, e.head].each()
            { if (!nodes.contains(it)) nodes.add(it) }
    return new ResultGraph(this, this)
  }

  def Graph add(Object o) {
    def Node node = decorator.wrap(o)
    nodes.add(node);
    node.graph = this
    return new ResultGraph(this, this)
  }



  def Graph connect(Node tail, Node head) {

    add(decorator.createEdge(tail, head, null, false))
  }

  def Graph connect(Node tail, Node head, Node userData) { add(decorator.createEdge(tail, head, userData, false)) }

  def Graph direct(Node tail, Node head) { add(decorator.createEdge(tail, head, null, true)) }

  def MetaContext context() {
    return null;  //To change body of implemented methods use File | Settings | File Templates.
  }


  def Graph direct(Node tail, Node head, Node userData) { add(decorator.createEdge(tail, head, userData, true)) }

  def dump() {
    println "Graph:"
    nodes.each() { Node node -> node.dump() }
  }
}

